﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pixels.Logic
{
    public enum TerrainType
    {
        none,
        rocks, // normal terrain, no bonuses or penalties
        ubound
    }

    public class Tile
    {
        private readonly int _x;
        private readonly int _y;
        private readonly Map _map;
       

        public TerrainType Type { get; private set; }

        public int x { get { return _x; } }
        public int y { get { return _y; } }

        public Map Map { get { return _map; } }

        internal Tile(Map map, int x, int y) {
            _x = x; _y = y; _map = map;
            this.Type = TerrainType.none;

        }

        public void changeType(TerrainType newType) {
            this.Type = newType;
        }

        public Tile Neighbour(Direction dir) {
            var off = dir.offset();
            return Map[x + off.x, y + off.y];            
        }

        public Ur.crds3 worldCenter { get { return new Ur.crds3(0.5f + this._x, 0.5f + this._y, 0f);  } }


        private HashSet<TileEntity> entities = new HashSet<TileEntity>();
        private TileEntity[] _entityProcessedArray;

        public TileEntity[] allEntities {
            get {
                if (_entityProcessedArray == null) {
                    _entityProcessedArray = new TileEntity[entities.Count ];
                    entities.CopyTo(_entityProcessedArray);
                }
                return _entityProcessedArray;
            }
        }

        public Structure StructureOnTile {
            get {
                foreach (var entity in allEntities) if (entity is Structure) return entity as Structure;
                return null;
            }
        }
        
        public bool HasStructure { get { return StructureOnTile != null; } }

        /// <summary> You do not call this. TileEntity calls this. </summary>        
        internal void lostEntity(TileEntity tileEntity) {
            this.entities.Remove(tileEntity);
            _entityProcessedArray = null;
        }

        /// <summary> You do not call this. TileEntity calls this. </summary>
        internal void gainedEntity(TileEntity tileEntity) {
            this.entities.Add(tileEntity);
            _entityProcessedArray = null;
        }

    }

    public enum Direction
    {
        none, north, northeast, east, southeast, south, southwest, west, northwest, ubound
    }
    static class Directions
    {
        static private Ur.int2[] offsets =  { 
            new Ur.int2(-1000,-1000),
            new Ur.int2(0,-1), // north
            new Ur.int2(1,-1), // ne
            new Ur.int2(1, 0),  // e
            new Ur.int2(1,1), // se
            new Ur.int2(0,1), // s
            new Ur.int2(-1,1),   // sw
            new Ur.int2(-1,0),
            new Ur.int2(-1,-1) //ne
                                            };

        static public Ur.int2 offset(this Direction dir) {
            return offsets[(int)dir];
        }
    }
}
